using System;
using dnAnalytics.Nli;

/// <summary>
/// Matrix multiplication where a is a triangular matrix. b = alpha * a * b
/// </summary>
internal class Program {
	[STAThread]
	private static void Main() {
		//use the MKL BLAS provider
		IBlas blas = Blas.Provider(BlasProvider.Mkl);

		/*
			1 2 3        1 1 1           14 14 14          1  3  6
		a = 0 1 2    b = 2 2 2   a * b =  8  8  8  b * a = 2  6 12
			0 0 1        3 3 3            3  3  3          3  9 18
		*/

		//row ordering
		double[] a = new double[] {1, 0, 0, 2, 1, 0, 3, 2, 1};
		double[] b = new double[] {1, 2, 3, 1, 2, 3, 1, 2, 3};

		double alpha = 1;

		///b = a * b
		blas.Dtrmm(BlasOrderType.Column, BlasSideType.Left, BlasUpLoType.Upper, BlasTransType.NoTrans, BlasDiagType.Unit, 3, 3, alpha, a, 3, b, 3);
		foreach (double value in b) {
			Console.WriteLine(value);
		}
		Console.WriteLine();

		//reset b
		b = new double[] {1, 2, 3, 1, 2, 3, 1, 2, 3};

		///b = b * a
		blas.Dtrmm(BlasOrderType.Column, BlasSideType.Right, BlasUpLoType.Upper, BlasTransType.NoTrans, BlasDiagType.Unit, 3, 3, alpha, a, 3, b, 3);
		foreach (double value in b) {
			Console.WriteLine(value);
		}
		Console.WriteLine();

		//reset b
		b = new double[] {1, 2, 3, 1, 2, 3, 1, 2, 3};

		//lets add values to the lower triangle of a.
		//Trmm will ingore them
		a = new double[] {1, -9, -9, 2, 1, -9, 3, 2, 1};

		//we get the same value as above
		blas.Dtrmm(BlasOrderType.Column, BlasSideType.Right, BlasUpLoType.Upper, BlasTransType.NoTrans, BlasDiagType.Unit, 3, 3, alpha, a, 3, b, 3);
		foreach (double value in b) {
			Console.WriteLine(value);
		}
		Console.WriteLine();

		/* 
		Output:
		14
		8
		3
		14
		8
		3
		14
		8
		3

		1
		2
		3
		3
		6
		9
		6
		12
		18

		1
		2
		3
		3
		6
		9
		6
		12
		18
		*/
	}
}